﻿
#If RETIRED Then

Imports std

Public Class netTransData
    Implements ICloneable

    Public Const stopChar As Byte = 0
    Public Const escapeChar As Byte = 255
    Public Const displayRange As Int64 = 128

    'store data after convertBytes
    'first = start, second = length
    Protected Friend _field As vector(Of pair(Of Int64, Int64))
    Protected Friend _data As bytes

    Public Shared Function convertBytes(ByRef value As bytes, ByRef rtn As bytes) As Boolean
        If value Is Nothing Then
            Return False
        Else
            Dim len As Int64 = value.size
            Dim i As Int64
            Dim j As Int64
            If rtn Is Nothing Then
                rtn = New bytes
            Else
                rtn.clear()
            End If
            rtn.size = (len << 1) + 1
            j = 0
            For i = 0 To len - 1
                Select Case value(i)
                    Case stopChar
                        rtn(j) = escapeChar
                        j += 1
                        rtn(j) = stopChar
                        j += 1
                    Case escapeChar
                        rtn(j) = escapeChar
                        j += 1
                        rtn(j) = escapeChar
                        j += 1
                    Case Else
                        rtn(j) = value.data(i)
                        j += 1
                End Select
            Next
            rtn(j) = stopChar
            j += 1
            rtn.size = j

            Return True
        End If
    End Function

    Public Shared Function convertBytesBack(ByRef value As bytes, ByRef rtn As bytes) As Boolean
        If value Is Nothing Then
            Return False
        Else
            If rtn Is Nothing Then
                rtn = New bytes
            End If
            Dim len As Int64 = 0
            len = value.size()
            rtn.size = len
            Dim i As Int64
            Dim j As Int64
            j = 0
            For i = 0 To len - 1
                Select Case value(i)
                    Case escapeChar
                        i += 1
                        rtn(j) = value(i)
                        j += 1
                    Case stopChar
                        assert(i = len - 1, "meet stopChar, but i <> len - 1")
                        Exit For
                    Case Else
                        rtn(j) = value(i)
                        j += 1
                End Select
            Next

            rtn.size = j
            Return True
        End If
    End Function

    Public Function available() As Boolean
        Dim i As Int64
        For i = 0 To _field.size() - 1
            If _field(i).second = 0 OrElse _data.size <= _field(i).first + _field(i).second Then
                Exit For
            End If
        Next

        If i < _field.size() Then
            Return False
        Else
            Return True
        End If
    End Function

    Public Function insert(ByRef values() As bytes, Optional ByVal start As Int64 = 0 _
                            , Optional ByVal size As Int64 = npos) As Boolean
        If size = npos Then
            size = values.Length()
        Else
            size += start
        End If
        Dim i As Int64
        For i = start To size - 1
            If Not insert(values(i)) Then
                Exit For
            End If
        Next
        Return i = size
    End Function

    Public Function insert(ByRef value As bytes) As Boolean
        Dim afterConvert As bytes = Nothing
        If convertBytes(value, afterConvert) Then
            Dim start As Int64 = 0
            start = _data.size()
            _data += afterConvert
            _field.push_back(make_pair(start, _data.size() - start))
            Return True
        Else
            Return False
        End If
    End Function

    Public Function insert(Of valueT)(ByRef value As valueT) As Boolean
        Dim internal As bytes = New bytes(encoding.utf8.GetBytes(Convert.ToString(value)))
        Return insert(internal)
    End Function

    Public Function take(ByVal index As Int64, ByRef buff As bytes) As Boolean
        buff = at(index)
        Return Not buff Is Nothing
    End Function

    Public Function take(ByVal index As Int64) As bytes
        Return at(index)
    End Function

    Public Function take(Of T)(ByVal index As Int64, ByRef value As T) As Boolean
        Dim field As bytes = Nothing
        field = take(index)
        If field Is Nothing Then
            Return False
        Else
            Dim str As String
            If Not field.data Is Nothing Then
                str = encoding.utf8.GetString(field.data, 0, field.size)
                value = CType(str, Object)
            End If
            Return True
        End If
    End Function

    Public Function take(Of valueT)(ByVal index As Int64) As valueT
        Dim temp As valueT
        If take(index, temp) Then
            Return temp
        Else
            Return Nothing
        End If
    End Function

    Public ReadOnly Property data(ByVal index As Int64) As bytes
        Get
            Return at(index)
        End Get
    End Property

    Default Public ReadOnly Property at(ByVal index As Int64) As bytes
        Get
            Dim rtn As bytes = Nothing
            If _field.availableIndex(index) _
                AndAlso convertBytesBack(New bytes(_data.data, _field(index).first, _field(index).second), rtn) Then
                Return rtn
            Else
                Return Nothing
            End If
        End Get
    End Property

    Public Function export(ByRef buff() As Byte, ByVal start As Int64, ByRef size As Int64) As Boolean
        size = _data.size()
        If buff Is Nothing OrElse buff.Length < start + size Then
            If start = 0 Then
                ReDim buff(size - 1)
            Else
                ReDim Preserve buff(start + size - 1)
            End If
        End If
        memcpy(buff, start, _data.data, 0, size)
        Return True
    End Function

    Public Function export(ByRef buff() As Byte, ByRef size As Int64) As Boolean
        Return export(buff, 0, size)
    End Function

    Public Function import(ByRef buff() As Byte, ByVal start As Int64, ByVal size As Int64) As Boolean
        Dim markstart As Int64 = 0
        markstart = _data.size()
        _data += New bytes(buff, start, size)
        Dim lastStopChar As Int64 = 0
        If _data(markstart) = stopChar Then
            _field.push_back(make_pair(markstart, CType(1, Int64)))
            lastStopChar = markstart
        Else
            lastStopChar = markstart - 1
        End If
        For markstart = markstart + 1 To _data.size() - 1
            If _data(markstart) = stopChar AndAlso _data(markstart - 1) <> escapeChar Then
                If isdebugmode() Then
                    assert(_data(lastStopChar) = stopChar, "_data(lastStopChar) = stopChar")
                End If
                _field.push_back(make_pair(lastStopChar + 1, markstart - lastStopChar - 1))
                lastStopChar = markstart
            End If
        Next
    End Function

    Public Function import(ByRef buff() As Byte) As Boolean
        Return import(buff, 0, buff.Length)
    End Function

    Public Function fieldCount() As Int64
        Return _field.size()
    End Function

    Public Sub copy(ByRef value As netTransData)
        base.copy(_field, value._field)
        base.copy(_data, value._data)
    End Sub

    Public Sub clone(ByRef value As netTransData)
        copy(value)
    End Sub

    Public Sub New()
        clear()
    End Sub

    Public Sub New(ByRef value As netTransData)
        clear()
        copy(value)
    End Sub

    Public Sub clear()
        If _field Is Nothing Then
            _field = New vector(Of pair(Of Int64, Int64))
        Else
            _field.clear()
        End If
        If _data Is Nothing Then
            _data = New bytes
        Else
            _data.clear()
        End If
    End Sub

    Protected Overrides Sub Finalize()
        clear()
        MyBase.Finalize()
    End Sub

    Public Function display() As String
        Dim i As Int64
        Dim str As String = Nothing
        For i = 0 To min(displayRange, _field.size()) - 1
            Dim temp As bytes = Nothing
            temp = at(i)
            assert(Not temp Is Nothing, "cannot get data, index " + Convert.ToString(i))
            str += encoding.utf8.GetString(temp.data)
        Next

        Return str
    End Function

    Public Function Clone() As Object Implements System.ICloneable.Clone
        Dim rtn As netTransData = Nothing
        rtn = New netTransData(Me)
        Return rtn
    End Function
End Class

#End If
